#!/usr/bin/python2
#coding:utf8

import commands
import os
import sys
import errno
import socket
import subprocess
import fcntl
import time
import threading
import struct
import urllib2
import re
import signal
import json
import httplib
import paramiko
import logging
import logging.handlers
from paramiko.client import SSHException

msg_lock = threading.Lock()

LOG = logging.getLogger('Ump.proxy.utils')

def _print1(str1):
    LOG.info("\x1b[1;32m%s\x1b[0m" % (str1))

def _print2(str1):
    LOG.info("\x1b[1;31m%s\x1b[0m" % (str1))

def _print3(str1):
    LOG.info("\x1b[0;33m%s\x1b[0m" % (str1))

def _dwarn(str1, ttyonly = False):
    if msg_lock.acquire(5):
        if (os.isatty(sys.stdout.fileno()) or ttyonly):
            sys.stdout.write("\x1b[1;01m%s\x1b[0m\n" % (str1))
        else:
            sys.stdout.write("[%s %s] WARNING:%s\n" % (int(time.time()), time.strftime('%F %T'), str1))
        msg_lock.release()

def _derror(str1, ttyonly = False):
    if (msg_lock.acquire(5)):    
        if (os.isatty(sys.stderr.fileno()) or ttyonly):
            sys.stderr.write("\x1b[1;31m%s\x1b[0m\n" % (str1))
        else:
            sys.stderr.write("%s\n" % (str1))
        msg_lock.release()

def _dmsg(str1, ttyonly = False):
    if (msg_lock.acquire(5)):
        if (os.isatty(sys.stdout.fileno()) or ttyonly):
            sys.stdout.write("%s\n" % (str1))
            #sys.stdout.write("\x1b[0;33m%s\x1b[0m\n" % (str1))
        else:
            sys.stdout.write("[%s %s] INFO:%s\n" % (int(time.time()), time.strftime('%F %T'), str1))
        msg_lock.release()
            
def _get_value(path):
    size = os.path.getsize(path)
    fd = open(path, 'r')
    buf = fd.read(size)
    fd.close()
    return buf

def _set_value(path, buf):
    fd = open(path, 'w')
    fd.write(buf)
    fd.close()

def _net_blocked(hostname):
    s = hostname.split('/')
    path = "/dev/shm/lich/blocklist/" + s[0]
    if (os.path.exists(path)):
        return True
    else:
        return False

def _scape(s):
    s = s.replace("[", "\[")
    s = s.replace("]", "\]")
    return s

def _check_config(configfile, key, split, value, fix):
    cmd = "grep -P '^[\t ]*%s[\t ]%s[\t ]*%s$' %s > /dev/null" % (_scape(key), split, value, configfile)
    #LOG.info(cmd)
    ret = subprocess.call(cmd, shell=True)
    if (ret):
        #_dwarn(cmd + " fail")
        if (fix):
            cmd = "grep -P '^[\t ]*%s' %s > /dev/null" % (_scape(key), configfile)
            #LOG.info(cmd)
            ret = subprocess.call(cmd, shell=True)
            if (ret):
                cmd = "echo '%s %s %s' >> %s" %(key, split, value, configfile)
                ret = subprocess.call(cmd, shell=True)
                if (ret):
                    raise Exception("sysctl set fail ret %u" % (ret))
                _dmsg(cmd)
            else:
                if (key.find('/') != -1 or split.find('/') != -1 or value.find('/') != -1):
                    cmd = "sed -i 's:^[\t ]*%s.*$:%s %s %s:g' %s > /dev/null" % (_scape(key), key, split, value, configfile)
                else:
                    cmd = "sed -i 's/^[\t ]*%s.*$/%s %s %s/g' %s > /dev/null" % (_scape(key), key, split, value, configfile)
                #LOG.info(cmd)
                ret = subprocess.call(cmd, shell=True)
                if (ret):
                    raise Exception("sysctl set fail ret %u" % (ret))
                _dmsg(cmd)
        else:
            raise Exception("sysctl check fail ret %u" % (ret))

def _check_crontab(plan, task, log):
    cmd = "grep '%s' /etc/crontab > /dev/null" % (task)
    #LOG.info(cmd)
    ret = subprocess.call(cmd, shell=True)
    if (ret == 0):
        cmd = "sed -i '/%s/d' /etc/crontab" % (task.replace('/', '\/'))
        #LOG.info(cmd)
        os.system(cmd)
    cmd = "echo '%s %s >> %s' >> /etc/crontab" % (plan, task, log)
    #LOG.info(cmd)
    os.system(cmd)

class Exp(Exception):
    def __init__(self, errno, err, out = None):
        self.errno = errno
        self.err = err
        self.out = out

    def __str__(self):
        exp_info = 'errno:%s, err:%s'%(self.errno, self.err)
        if self.out is not None:
            exp_info += ' stdout:' + self.out
        return repr(exp_info)

def _str2dict(s):
    if (s[-1] == '\n'):
        s = s[:-1]

    a = s.split('\n')
    d = {}
    for i in a:
        p = i.split(':')
        if (d.get(p[0])):
            raise Exp(errno.EEXIST, "dup key exist")
        try:
            d[p[0].strip()] = p[1].strip()
        except IndexError as err:
            LOG.info("str %s" % (s))
            raise
    return d

def _getrack(name):
    r = re.compile("([^.]+)\.([^.]+)\.([^.]+)")
    m = r.match(name)
    if (m == None):
        r = re.compile("([^.]+)\.([^.]+)")
        m = r.match(name)
        if (m == None):
            return "default"
        else:
            return m.groups()[0]
    else:
        return m.groups()[1]

def _exec_remote(host, cmd, user = "root", password=None, timeout = 1):
    if (_net_blocked(host)):
        raise Exp(errno.ENOENT, "blocked")

    s = paramiko.client.SSHClient()
    s.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
    try:
        s.connect(host, 22, user, password, timeout = timeout)
        stdin, stdout, strerr = s.exec_command(cmd)
        str1 = stdout.read()
        str2 = strerr.read()
    except socket.timeout as err:
        raise Exp(err.errno, err.strerror)
    except socket.error as err:
        raise Exp(err.errno, err.strerror)
    except paramiko.AuthenticationException as err:
        raise Exp(250, 'Authentication failed')
    s.close()

    return str1, str2

def _exec_http(host, cmd, user = "root", password=None, timeout = 1):
    if (_net_blocked(host)):
        raise Exp(errno.ENOENT, "blocked")

    url = 'http://' + host + ':27901/' + urllib2.quote(cmd)
    #LOG.info(url)
    req = urllib2.Request(url)
    try:
        response = urllib2.urlopen(req)
        rep = response.read()
    except socket.timeout as err:
        raise Exp(err.errno, err.strerror)
    except socket.error as err:
        raise Exp(err.errno, err.strerror)

    #LOG.info(rep)
    #LOG.info(type(rep))
    res = json.loads(rep) 
    stdout = res['stdout']
    stderr = res['stderr']
    err = res['errno']
    return stdout, stderr

def _put_remote(host, local, remote, user = "root", password=None, timeout = 1):
    s = paramiko.client.SSHClient()
    s.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
    try:
        s.connect(host, 22, user, password, timeout = timeout)
        f = s.open_sftp()
        f.put(local, remote)
    except socket.timeout as err:
        raise Exp(err.errno, err.strerror)
    except socket.error as err:
        raise Exp(err.errno, err.strerror)
    except paramiko.ssh_exception.AuthenticationException as err:
        raise Exp(250, 'Authentication failed')
    f.close()
    s.close()

def _lock_file(key, timeout=3600, p=True):
    key = os.path.abspath(key)
    parent = os.path.split(key)[0]
    os.system("mkdir -p " + parent)

    while (1):
        if p:
            _dmsg("lock " + key)
        lock_fd = open(key, 'a')

        try:
            fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
        except IOError as err:
            #LOG.info("errno %d" % err.errno)
            if err.errno == errno.EAGAIN:
                fd = open(key, 'r')
                s = fd.read()
                fd.close()
                if (',' in s):
                    (ltime, pid) = s.split(',')
                    ltime = int(ltime)
                    pid = int(pid)
                    now = int(time.time())
                    if (now > ltime and ltime != -1):
                        _derror("%s locked by %d time %u, just kill it" % (key, pid, now - ltime))
                        os.system("kill -2 %d" % pid)
                        lock_fd.close()
                        os.unlink(key)
                        continue
                    else:
                        _derror("%s locked, %d before timeout, exit..." % (key, ltime - now))
                        exit(errno.EBUSY)
                else:
                    os.unlink(key)
                    lock_fd.close()
                    continue
            else:
                raise

        lock_fd.truncate(0)
        if timeout == -1:
            s = '-1,' + str(os.getpid())
        else:
            s = str(int(time.time()) + timeout) + ',' + str(os.getpid())
        lock_fd.write(s)
        lock_fd.flush()
        break
    return lock_fd

def _human_readable(num, idx=0):
    u = ['B', 'K', 'M', 'G', 'T']
    #LOG.info("num %u idx %u" % (num, idx))
    if (num / 1024 < 1):
        return str(int(num)) + u[idx]
    else:
        return _human_readable(num / 1024, idx + 1)

def _human_unreadable(_size):
    unit = _size[-2]
    num = float(_size[0:-2])
    assert(_size[-1] == 'B')
    assert(unit in "kKmMgGtT")
    if (unit in ("kK")):
        return num * 1024
    elif (unit in ("Mm")):
        return num * 1024 * 1024
    elif (unit in ("Gg")):
        return num * 1024 * 1024 * 1024
    else:
        return num * 1024 * 1024 * 1024 * 1024

def alarm_handler(signum, frame):
    raise Exp(errno.ETIME, "command execute time out")

def _exec_pipe(cmd, retry = 3, p = True, timeout = 0):
    env = {"LANG" : "en_US", "LC_ALL" : "en_US", "PATH" : os.getenv("PATH")}
    #cmd = self.lich_inspect + " --movechunk '%s' %s  --async" % (k, loc)
    _retry = 0
    cmd1 = ''
    for i in cmd:
        cmd1 = cmd1 + i + ' '
    if (p):
        _dmsg(cmd1)
    while (1):
        p = None
        try:
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env = env)
        except Exception, e:
            raise Exp(e.errno, cmd1 + ": command execute failed")

        if timeout != 0:
            signal.signal(signal.SIGALRM, alarm_handler)
            signal.alarm(timeout)
        try:
            stdout, stderr = p.communicate()
            signal.alarm(0)
            ret = p.returncode
            if (ret == 0):
                return stdout
            elif (ret == errno.EAGAIN and _retry < retry):
                _retry = _retry + 1
                time.sleep(1)
                continue
            else:
                #_derror("cmd %s" % (cmd1))
                raise Exp(ret, cmd1 + ": " + os.strerror(ret))

        except KeyboardInterrupt as err:
            _dwarn("interupted")
            p.kill()
            exit(errno.EINTR)

def _exec_pipe1(cmd, retry = 3, p = True, timeout = 0):
    env = {"LANG" : "en_US", "LC_ALL" : "en_US", "PATH" : os.getenv("PATH")}
    #cmd = self.lich_inspect + " --movechunk '%s' %s  --async" % (k, loc)
    _retry = 0
    cmd1 = ''
    for i in cmd:
        cmd1 = cmd1 + i + ' '
    if (p):
        _dmsg(cmd1)
    while (1):
        p = None
        try:
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env = env)
        except Exception, e:
            raise Exp(e.errno, cmd1 + ": command execute failed")

        if timeout != 0:
            signal.signal(signal.SIGALRM, alarm_handler)
            signal.alarm(timeout)
        try:
            stdout, stderr = p.communicate()
            signal.alarm(0)
            ret = p.returncode
            if (ret == 0):
                return stdout, stderr
            elif (ret == errno.EAGAIN and _retry < retry):
                _retry = _retry + 1
                time.sleep(1)
                continue
            else:
                #_derror("cmd %s" % (cmd1))
                #return stdout, stderr
                raise Exp(ret, stderr, stdout)
        except KeyboardInterrupt as err:
            _dwarn("interupted")
            p.kill()
            exit(errno.EINTR)

def _exec_big(cmd, retry = 3, p = True, print_result=False):
    #cmd = self.lich_inspect + " --movechunk '%s' %s  --async" % (k, loc)
    _retry = 0
    cmd1 = ''
    for i in cmd:
        cmd1 = cmd1 + i + ' '
    if (p):
        _dmsg(cmd1)
    while (1):
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE)

        try:
            res = ""
            while (p.poll() == None):
                r = p.communicate()[0]
                res += r
                if (print_result):
                    LOG.info(r),

            ret = p.wait()
            if (ret == 0):
                return res
            elif (ret == errno.EAGAIN and _retry < retry):
                _retry = _retry + 1
                time.sleep(1)
                continue
            else:
                #_derror("cmd %s" % (cmd1))
                raise Exp(ret, cmd1 + ": " + os.strerror(ret))
        except KeyboardInterrupt as err:
            _dwarn("interupted")
            p.kill()
            exit(errno.EINTR)

def _exec_shell(cmd, retry = 3, p = True):
    if (p):
        _dmsg (cmd)
    _retry = 0
    while (1):
        try:
            p = subprocess.Popen(cmd, shell=True)
            stdout, stderr = p.communicate()
            ret = p.returncode
            if (ret == 0):
                return
            elif (ret == errno.EAGAIN and _retry < retry):
                _retry = _retry + 1
                time.sleep(1)
                continue
            else:
                #_derror("cmd " + cmd + " : " + os.strerror(ret))
                #exit(1)
                raise Exp(ret, "%s: %s" % (cmd, os.strerror(ret)))
        except KeyboardInterrupt as err:
            _dwarn("interupted")
            p.kill()
            exit(errno.EINTR)

def _str2list(str1):
    r = re.compile("\[[^\]]+]")
    res = r.findall(str1)
    if (len(res) == 0):
        return [str1]
    elif (len(res) > 1):
        ret = errno.EINVAL
        raise Exp(ret, os.strerror(ret))

    left = r.split(str1)
    if (len(left) != 2):
        ret = errno.EINVAL
        raise Exp(ret, os.strerror(ret))

    newlist = []
    res = res[0][1:-1]
    lst = res.split(',')
    for i in lst:
        if ('-' in i):
            r1 = i.split('-')
            r1 = range(int(r1[0]), int(r1[1]) + 1)
            newlist = newlist + r1
        else:
            newlist.append(int(i))

    newlist = list(set(newlist))
    result = []

    if (left[1] == ''):
        for i in newlist:
            result.append(left[0] + str(i))
    else:
        for i in newlist:
            result.append(str(i) + left[1])

    return result

def _strjoin(a1, a2):
    a3 = []
    for i in a1:
        for j in a2:
            a3.append(i + '.' + j)

    return a3
    
def _str2hosts1(str1):
    a1 = str1.split('.')

    if (len(a1) > 3):
        ret = errno.EINVAL
        raise Exp(ret, os.strerror(ret))
    
    a2 = []
    for i in a1:
        a2.append(_str2list(i))

    a3 = []
    if (len(a1) == 1):
        return a2[0]
    elif (len(a1) == 2):
        return _strjoin(a2[0], a2[1])
    else:
        return _strjoin(_strjoin(a2[0], a2[1]), a2[2])

def _isip(str1):
    try:
        m = re.match("^\d+\.\d+.\d+\.\d+$", str1).group()
    except Exception, e:
        return False
    return True

def _str2hosts(list1):
    newlist = []
    for i in list1:
        if (_isip(i)):
            newlist = newlist + [i]
        else:
            newlist = newlist + _str2hosts1(i)

    return newlist

def _star2hosts(hostlist):
    newlist = []
    for i in hostlist:
        if (i.find('*') < 0):
            newlist.append(i)
            continue
        i = i.replace('.', '\.')
        i = i.replace('*', '.*')
        cmd = "grep %s /etc/hosts" % i;
        res = os.popen(cmd).read()
        for host in res.split('\n'):
            if (len(host) > 0 and host.strip()[0] != '#'):
                r = re.compile("^"+i+"$")
                m = r.match(host.split()[-1])
                if (m != None):
                    newlist.append(host.split()[-1])

    return newlist

def _check_hosts(hostlist, nohosts):
    for i in hostlist:
        if (nohosts):
            if not _isip(i):
                raise Exp(errno.EINVAL, "nohosts type only allow ip address")

    return 0

def _search_hosts(hosts, regs):
    s = ''
    for i in hosts:
        s = s + i + '\n'

    newlist = []
    for i in regs:
        if (i[-1] == '*'):
            r = re.compile(i[:-1].replace('.', '\.') + "[^\\n]+")
            newlist = newlist + r.findall(s)
        else:
            newlist = newlist + [i];

    return list(set(newlist))

def _sshkey(host, passwd):
    while (1):
        os.system("if [ ! -f  /root/.ssh/id_dsa.pub ];then ssh-keygen -t dsa -P '' -f /root/.ssh/id_dsa ; fi")
        pub = _get_value('/root/.ssh/id_dsa.pub')
        private = _get_value('/root/.ssh/id_dsa')
        if "'" in pub or '"' in pub or "'" in private or '"' in private :
            os.system('rm -rf /root/.ssh/id_dsa*')
        else:
            break

    #remote_tmpkey = '/tmp/lich_authorized_key'
    try:
        cmd = "if [ ! -d /root/.ssh ]; then mkdir /root/.ssh; fi"
        cmd = cmd + " && echo '%s' >> /root/.ssh/authorized_keys" % (pub)
        cmd = cmd + " && echo '%s' > /root/.ssh/id_dsa.pub" % (pub)
        cmd = cmd + " && echo '%s' > /root/.ssh/id_dsa" % (private)
        cmd = cmd + " && chmod 0600 /root/.ssh/id_dsa"
        cmd = cmd + " && if [ -f /etc/init.d/iptables ];then /etc/init.d/iptables stop; setenforce 0;fi"
        #LOG.info(cmd)
        _exec_remote(host, cmd, 'root', passwd)
        #_exec_remote(host, "if [ ! -d /root/.ssh ]; then mkdir /root/.ssh; fi", "root", passwd)
        #_put_remote(host, "/root/.ssh/id_dsa.pub", remote_tmpkey, "root", passwd)
        #_exec_remote(host, "cat %s >> /root/.ssh/authorized_keys" % (remote_tmpkey) , "root", passwd)
    except socket.gaierror as err:
        raise Exp(err.errno, err.strerror)
    except SSHException as err:
        raise Exp(errno.EINVAL, str(err))

def _is_physic(dev):
    f = os.path.join("/sys/class/net/", dev, "device")
    return os.path.isdir(f)

def ___get_speed_ifaces(dev, ifaces):
    speeds = [(i, int(_get_speed(i))) for i in ifaces if _is_physic(i)]
    speeds_lower = [x for (x, y) in speeds if y < 1000]

    if (len(speeds) == 0):
        _derror("these is no physic dev with " + dev)
        return 100

    if (speeds_lower):
        _derror("these devs is lower speed: " + ",".join(speeds_lower))
        return 100

    return 1000

def __get_speed_bonding(dev):
    #cat /proc/net/bonding/bond0 |grep 'Slave Interface'
    ifaces = []
    s = _exec_pipe(["cat", '/proc/net/bonding/%s'%(dev)], 1, False)
    pre = "Slave Interface:"

    for i in s.strip().split("\n"):
        if (i.strip().startswith(pre)):
            ifaces.append((i.split(":")[-1]).strip())

    return ___get_speed_ifaces(dev, ifaces)

def __get_speed_bridge(dev):
    #brctl show virbr0|awk '{print $NF}'
    ifaces = []
    s = _exec_pipe(["brctl", 'show', dev], 1, False)

    for i in s.strip().split("\n"):
        if (len(i.strip().split()) >= 1):
            ifaces.append(i.strip().split()[-1])
    ifaces = ifaces[1:]

    return ___get_speed_ifaces(dev, ifaces)

def __get_speed_openvswitch(dev):
    s = _exec_pipe(["ovs-vsctl", 'list-ifaces', dev], 1, False)
    ifaces = s.strip().split("\n")

    return ___get_speed_ifaces(dev, ifaces)

def _get_speed(dev):
    s = _exec_pipe(["ethtool", '-i', dev], 1, False)
    d = _str2dict(s)
    if (d['driver'] in ['virtio_net']):
        _dwarn("%s is not recommended" % (d['driver']))
        return 1000

    if (d['driver'] == 'bonding'):
        speed = __get_speed_bonding(dev)
        if (speed < 1000):
            raise Exp(errno.ENOENT, "no network available")
        else:
            return speed

    if (d['driver'] == 'bridge'):
        speed = __get_speed_bridge(dev)
        if (speed < 1000):
            raise Exp(errno.ENOENT, "no network available")
        else:
            return speed

    if (d['driver'] == 'openvswitch'):
        speed = __get_speed_openvswitch(dev)
        if (speed < 1000):
            raise Exp(errno.ENOENT, "no network available")
        else:
            return speed

    s = _exec_pipe(["ethtool", dev], 1, False)
    r = re.search("10000baseT", s)
    if (r == None):
        r = re.search("1000baseT", s)
    if (r == None):
        raise Exp(errno.ENOENT, "no network available")

    r1 = re.search("\d+", r.group()).group()
    r = re.search("Speed:[^\n]+", s)
    r2 = re.search("\d+", r.group()).group()

    if (r1 != r2):
        raise Exp(errno.ENOENT, "device %s error" % (dev))
    else:
        return r1

def _get_addr(dev):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    mask = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, struct.pack('256s' , dev))[20:24])
    net = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s' , dev))[20:24])
    s.close()
    return (net, mask)

def _get_network():
    s = _exec_pipe(["ifconfig"], 1, False)
    lst = re.findall(r'^[^ \n]+', s, re.M)
    lst1 = {}
    for i in lst:
        if (i[-1] == ':'):
            i = i[:-1]
        try:
            lst1[i] = _get_addr(i)
        except IOError as err:
            #LOG.info("get %s error %s" % (i, str(err)))
            continue
    return lst1

def _net_mask(net, mask):
    return _ntoa(_aton(net) & _aton(mask))

def _ntoa(n):
    return socket.inet_ntoa(struct.pack('i', n))

def _aton(a):
    return struct.unpack('i', socket.inet_aton(a))[0]    

def mem_info():
    out = commands.getstatusoutput('free')
    if out[0] != 0:
        return {}
    outs  = out[1].strip().split('\n')
    _out001  = outs[1].split()
    _out002  = outs[2].split()
    _out003  = outs[3].split()
    return {'total': _out001[1], 'used': _out001[2], 
            'free': _out001[3], 'shared': _out001[4], 
            'buffers': _out001[5], 'cached': _out001[6],
            'buffcache_used': _out002[-2], 
            'buffcache_free': _out002[-1],
            'swap_total': _out003[-3], 
            'swap_used': _out003[-2], 'swap_free': _out003[-1],
            }
def network_info():
    interfaces = ethernets_get_all()
    network_info = []
    for i in interfaces:
        network_info.append(ethernet_info(i))
    return network_info

def ethernets_get_all():
    return os.listdir("/sys/class/net/")

def ethernet_info(eth):
    mac = None
    out = commands.getstatusoutput(
            "ip addr show %s|grep 'link\/ether'"%(eth))
    if out[0] == 0:
        mac  = out[1].strip().split()[1]

    ips = []
    out = commands.getstatusoutput(
            "ip addr show %s|grep 'inet' \
            |grep -v 'inet6'|awk '{print $2}'"%(eth))
    if out[0] == 0:
        ips  = out[1].strip().split()

    rb = None 
    out = commands.getstatusoutput(
            "ifconfig %s|grep 'RX packets' \
            |awk -F':' '{print $2}'|awk '{print $1}'"%(eth))
    if out[0] == 0:
        rb  = out[1].strip()

    tb = None 
    out = commands.getstatusoutput(
            "ifconfig %s|grep 'TX packets' \
            |awk -F':' '{print $2}'|awk '{print $1}'"%(eth))
    if out[0] == 0:
        tb  = out[1].strip()

    speed = None
    out = commands.getstatusoutput(
            "ethtool %s|grep Speed| awk '{print $2}'"%(eth))
    if out[0] == 0:
        speed  = out[1].strip()

    is_linked = 'no'
    out = commands.getstatusoutput(
            "ethtool %s|grep 'Link detected' \
            | awk -F':' '{print $2}'"%(eth))
    if out[0] == 0:
        is_linked  = out[1].strip()

    return {'ifname': eth, 'mac': mac, 'ips': ips, 
            'rx_bytes': rb, 'tx_bytes': tb, 
            'speed': speed, 'is_linked': is_linked}

def storage_info(mount_p):
    info = []
    out = commands.getstatusoutput("df|grep '%s'"%(mount_p))
    if out[0] != 0:
        return info
    lines = out[1].strip().split('\n')
    for l in lines:
        m = l.split()
        ms = {'device': m[0], 'size': m[1], 'used': m[2], 
                'avail': m[3], 'use_p': m[4], 'mount_point': m[5]}
        info.append(ms)
    return info

def uptime():
    ctime = None
    out = commands.getstatusoutput("uptime|awk '{print $1}'")
    if out[0] == 0:
        ctime  = out[1].strip()

    time = None
    out = commands.getstatusoutput("uptime|awk '{print $2, $3, $4, $5}'")
    if out[0] == 0:
        time  = out[1].strip()

    user = None
    out = commands.getstatusoutput("uptime|awk '{print $6, $7}'")
    if out[0] == 0:
        user  = out[1].strip()

    avg1 = None
    out = commands.getstatusoutput("uptime|awk '{print $8}'")
    if out[0] == 0:
        avg1  = out[1].strip()

    avg5 = None
    out = commands.getstatusoutput("uptime|awk '{print $9}'")
    if out[0] == 0:
        avg5  = out[1].strip()

    avg15 = None
    out = commands.getstatusoutput("uptime|awk '{print $10}'")
    if out[0] == 0:
        avg15  = out[1].strip()

    return {'current_time': ctime, 'time': time.strip(','), 
            'user': user.strip(','), 'avg1': avg1.strip(','), 
            'avg5': avg5.strip(','), 'avg15': avg15}

def cpu_info():
    cpu_num = None
    out = commands.getstatusoutput(
            "cat /proc/cpuinfo |grep processor|wc -l")
    if out[0] == 0:
        cpu_num  = out[1].strip()
    return cpu_num

def etchosts_update(hosts_file, ip, hostname):
    '''
    如果不存在该IP， 把该Ip的hostname写入到hosts_file中
    如果已经存在则更新
    '''
    lines = []
    ip_exist = False
    new_line = "%s %s\n"%(ip, hostname)

    if os.path.isfile(hosts_file):
        with open(hosts_file, 'r') as f:
            for line in f:
                if not line.strip():
                    lines.append(line)
                    continue

                if hostname == line.split()[1].strip():
                    raise Exp(errno.EINVAL, "hostname %s double" % (hostname))

                if ip == line.split()[0]:
                    lines.append(new_line)
                    ip_exist = True
                else:
                    lines.append(line)

    if not ip_exist:
        lines.append(new_line)
    
    os.system('echo "">%s'%(hosts_file))
    with open(hosts_file, 'w+') as f:
        for line in lines:
            f.write('%s'%(line))

def _read_cpu_usage():  
    """Read the current system cpu usage from /proc/stat."""  
    try:  
        fd = open("/proc/stat", 'r')  
        lines = fd.readlines()  
    finally:  
        if fd:  
            fd.close()  
    for line in lines:  
        l = line.split()  
        if len(l) < 5:  
            continue  
        if l[0].startswith('cpu'):  
            return l  
    return []  
  
def cpu_usage():  
    """ 
    get cpu avg used by percent 
    """  
    cpustr=_read_cpu_usage()  
    if not cpustr:  
        return 0  
    usni1=long(cpustr[1])+long(cpustr[2])+long(cpustr[3])\
            +long(cpustr[5])+long(cpustr[6])+long(cpustr[7])\
            +long(cpustr[4])  
    usn1=long(cpustr[1])+long(cpustr[2])+long(cpustr[3])  
    time.sleep(1)  
    cpustr=_read_cpu_usage()  
    if not cpustr:  
        return 0  
    usni2=long(cpustr[1])+long(cpustr[2])+float(cpustr[3])\
            +long(cpustr[5])+long(cpustr[6])+long(cpustr[7])\
            +long(cpustr[4])  
    usn2=long(cpustr[1])+long(cpustr[2])+long(cpustr[3])  
    cpuper=(usn2-usn1)/(usni2-usni1)  
    return 100*cpuper

def mutil_exec(func, args, timeout=None):
    #args = [[arg1, ...], ...]
    ts = []
    for i in args:
        t = threading.Thread(target=func, args=i)
        ts.append(t)

    [t.start() for t in ts]
    if timeout is None:
        [t.join() for t in ts]
    else:
        [t.join(timeout) for t in ts]

def mutil_call_remote(hosts, cmd, timeout=120):
    def _exec_remote_warp(host, cmd, rs):
        stdin, stdout, stderr, exp = None, None, None, None
        try:
            stdout = _exec_remote(host, cmd)
        except Exception, e:
            exp = str(e)
        rs.append({'host': host, 'stdout': stdout,
            'stderr': stderr, 'exp': exp})

    ts = []
    rs = []
    for i in range(len(hosts)):
        t = threading.Thread(
                target=_exec_remote_warp, args=[hosts[i], cmd, rs])
        ts.append(t)

    [t.start() for t in ts]
    [t.join() for t in ts]
    return rs

def _http_down(host, port, url, timeout=60):
    h2 = httplib.HTTPConnection(host,port,timeout=timeout)
    url = urllib2.quote(url)
    h2.putrequest("GET",url)
    h2.putheader('Content-Type', 'multipart/form-data')
    h2.putheader('Transfer-Encoding', 'chunked')
    h2.endheaders()
    r2 = h2.getresponse()
    content_length = r2.getheader("content-length")
    content = r2.read()
    return content, content_length

def main():
    LOG.info('just for test')
    #lock_fd = _lock_file("/tmp/test/mds/balance_lock", 20)

    retry = 10
    while (retry > 0):
        LOG.info(retry);
        retry = retry - 1
        time.sleep(1)

if __name__ == '__main__':
    print _get_speed("eth0")
    #print  __get_speed_openvswitch("br0")
    print  __get_speed_bridge("virbr0")
    print  __get_speed_bonding("bond0")
    #hosts = ['datacenter1.rack1.node1', 'datacenter1.rack2.node1''datacenter1.rack3.node1', 'datacenter1.rack4.node1']
    #for i in range(200):
        #hosts.append('datacenter1.rack1.node1%s'%(i))
    #r = mutil_call_remote(hosts, 'pwd')
    #print '-'*10
    #print r
    #main()
